Skip to content

Conversation

@innocenzi
Copy link
Member

@innocenzi innocenzi commented Jul 3, 2025

This pull request adds a new package, tempest/cryptography. It contains utilities to work with hashing, signing and encrypting. Later, we may add support for other cryptography-related features, though the three major ones are implemented.

Signing key

Note that after this pull request, we should encourage adding a SIGNING_KEY environment variable to .env files. However, no exception would be triggered unless the Signer or Encrypter are resolved from the container without it. Currently, nothing use them.

I thus added a familiar command key:generate. This generates a key using the currently-configured algorithm (AES_256_GCM by default) and adds it to .env (or updates it if it already exists).

Password hasher

The PasswordHasher interface is used to hash and verify passwords. The provided implementation can use either Argon2id or bcrypt, the former being the default.

$hasher = new GenericPasswordHasher(new ArgonConfig());


$hash = $hasher->hash($password);
$hasher->verify($password, $hash);

Signing

The Signer interface may be used to sign some data using a signing key, which would be configured globally. It could also verify the integrity of some data using a provided signature against the globally-configured key.

Under the hood, the provided implementation uses PHP's hmac functions and a new Timelock class for preventing against timing attacks.

$signer = new GenericSigner(new SigningConfig(
    algorithm: SigningAlgorithm::SHA256,
    key: env('SIGNING_KEY'),
    minimumExecutionDuration: false,
));

$signature = $signer->sign($data);
$signer->verify($data, $signature);

Encrypting

The Encrypter interface uses OpenSSL to encrypt and decrypt data, usually with the same key as the signing key. Under the hood, it also verifies the authenticity of the decrypted data using the signer.

$this->container->config(new EncryptionConfig(
    algorithm: EncryptionAlgorithm::AES_256_GCM,
    key: $key = EncryptionKey::generate(EncryptionAlgorithm::AES_256_GCM),
));

$this->container->config(new SigningConfig(
    algorithm: SigningAlgorithm::SHA256,
    key: $key,
    minimumExecutionDuration: false,
));

$encrypted = $this->encrypter->encrypt('important data');
$this->encrypter->decrypt($encrypted);

Timelock

This is a class inspired by Laravel's Timebox. It works exactly the same, except it uses tempest/clock under the hood.

$timelock->invoke(
      callback: $callback,
      duration: Duration::milliseconds(300),
);

@innocenzi innocenzi force-pushed the feat/cryptography branch from a355188 to 441fe92 Compare July 3, 2025 16:56
Copy link
Member

@brendt brendt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo after this is merged:

  • Mention in the docs that this is an experimental package

@innocenzi innocenzi requested a review from brendt July 29, 2025 16:21
@innocenzi innocenzi merged commit 439b49e into tempestphp:main Jul 30, 2025
86 of 87 checks passed
@innocenzi innocenzi deleted the feat/cryptography branch July 30, 2025 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants